<?php
/**
 * Created by PhpStorm.
 * User: shutao
 * Date: 2018/9/14
 * Time: 13:42
 */

namespace wechat\services;

use EasyWeChat\Factory;
use tt\common\help\LogHelp;
use ttcommon\base\Data;
use ttext\backend\admin\models\User;
use ttext\backend\admin\services\RbacService;
use wechat\models\WeConfig;
use yii\base\UserException;

class WeiXinService
{
    /**
     * 返回指定类型的一个配置
     * @param integer $type 类型，默认公众号
     * @return array ['id', 'appid','appsecret', 'token', 'encodingaeskey', 'debug', 'domain', 'type']
     * @throws
     */
    public static function defaultWeConfig($type = WeConfig::TYPE_GZH)
    {
        if (!$weixin = WeConfig::find()
            ->select(['id', 'appid', 'appsecret', 'token', 'encodingaeskey', 'debug', 'domain', 'type'])
            ->where(['status' => WeConfig::IS_DEFAULT_YES, 'type' => $type])->asArray()->one()) {
            throw new UserException('还没有激活的' . WeConfig::typeText($type) . '设置');
        }
        return $weixin;
    }

    /**
     * 通过 appid 查询指定配置信息
     * @param string $appid
     * @param null $status 指定状态，默认为 null
     * @return array ['id', 'appid','appsecret', 'token', 'encodingaeskey', 'debug', 'domain', 'type']
     */
    public static function weConfigFromAppid($appid, $status = null)
    {
        $query = WeConfig::find()
            ->select(['id', 'appid', 'appsecret', 'token', 'encodingaeskey', 'debug', 'domain', 'type'])
            ->where(['appid' => $appid]);
        if (!is_null($status)) {
            $query->andWhere(['status' => $status]);
        }
        return $query->asArray()->one();
    }

    /**
     * 使用指定的配置来初始化一个应用实例
     * @param array $weConfig 公共号配置
     * @param bool $cache
     * @return \EasyWeChat\OfficialAccount\Application
     * https://www.easywechat.com/docs/master/zh-CN/official-account/configuration
     * @throws
     */
    public static function app(&$weConfig = [], $cache = true)
    {
        static $app;
        if (!$app || !$cache) {
            // 基础的配置信息
            if (!$weConfig) {
                $weConfig = self::defaultWeConfig();
            }
            $config = [
                'app_id' => $weConfig['appid'],
                'secret' => $weConfig['appsecret'],
                'token' => $weConfig['token'],
                'aes_key' => '',                    // EncodingAESKey，兼容与安全模式下请一定要填写！！！
                'response_type' => 'array',
                'log' => [
                    'level' => 'debug', // debug/info/notice/warning/error/critical/alert/emergency
                    'file' => Data::hasValue($weConfig, 'log.file', PATH_DATA . 'log/wechat.log')
                ],
                // https://www.easywechat.com/docs/master/zh-CN/official-account/oauth
                'oauth' => [
                    'scopes' => ['snsapi_userinfo'], // 公众平台网页授权获取用户信息
                    // 注意：这里绝对不能添加 \Yii::$app->request->hostInfo .
                    'callback' => '/?r=wechat/server/callback&appid=' . $weConfig['appid'], // 授权回调URL (未urlencode编码的URL)
                ]
            ];
            // 初始化公众号应用实例
            $app = Factory::officialAccount($config);

//            pr($app);
        }
        return $app;
    }

    /**
     * 初始化小程
     * @param array $weConfig ['id', 'appid', 'appsecret', 'token', 'encodingaeskey', 'debug', 'domain', 'type']
     * @param bool $cache
     * @return \EasyWeChat\MiniProgram\Application
     * @throws UserException
     */
    public static function xcxApp(&$weConfig = [], $cache = true)
    {
        static $app;
        // https://www.easywechat.com/docs/master/mini-program/index
        if (!$app || !$cache) {
            if (!$weConfig) {
                $weConfig = self::defaultWeConfig(WeConfig::TYPE_XCX);
            }
            $config = [
                'app_id' => $weConfig['appid'],
                'secret' => $weConfig['appsecret'],
                // 返回的类型
                'response_type' => 'array',
                'log' => [
                    'level' => 'debug', // debug/info/notice/warning/error/critical/alert/emergency
                    'file' => Data::hasValue($weConfig, 'log.file', PATH_DATA . 'log/xcx.' . $weConfig['id'] . '.log')
                ],
            ];
            $app = Factory::miniProgram($config);
        }
        return $app;
    }

    public static function isWechat()
    {
        return strpos($_SERVER['HTTP_USER_AGENT'], "MicroMessenger") !== false;
    }

    /**
     * 通过 appid 创建一个应用实例
     * @param string $appid
     * @return \EasyWeChat\OfficialAccount\Application
     */
    public static function appFromAppid($appid = '')
    {
        $config = $appid ? self::weConfigFromAppid($appid) : null;
        return self::app($config);
    }


    /**
     * 如果未登录，则使用微信授权登录；通常添加放在需要授权的业务逻辑页面上;
     * @param string $appid 应用的 appid
     * @param string $target_url 回调地址，如果不设置，则从 URL 中读取 redirect_uri 参数；注意：不要设置成当前页面地址，否则可能在授权成功后，跳转回来造成循环
     */
    public static function wechatOauth($appid, $target_url = '')
    {
        if (!RbacService::isLogin()) {

            $app = self::appFromAppid($appid);
            $oauth = $app->oauth;
            $target_url = $target_url ?: Data::hasValue($_GET, 'redirect_uri', '');
            if ($target_url) {
                \Yii::$app->session->set('target_url', $target_url);
            }
            // test: 记录下回调域名
            LogHelp::message($oauth->redirect()->getTargetUrl(), 'wechatOauth');
            $oauth->redirect()->send();
            exit;
        }
        LogHelp::message('user is login:' . RbacService::uid(), 'wechatOauth');
    }

    /**
     * 用户注册，并返回其 id 号
     * https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140454
     * @param string $unionid 用户的唯一识别，或者用户的 openid(fromUserName)
     * @return int 当前微信用户在 user 表中所注册的 id 号
     * @throws \Exception
     */
    public static function registerIfNotExits($unionid)
    {
        // 关注时，注册
        $uuid = substr($unionid, 0, 77);
        try {
            if (!User::find()->where(['userid' => $uuid])->exists()) { // 为账号注册
                $sql = 'INSERT INTO `' . User::tableName() . '` (userid,`status`, created_at, updated_at) VALUES ("' . $uuid . '",' . User::STATUS_ACTIVE . ',' . time() . ',' . time() . ')';
                \Yii::$app->db->createCommand($sql)->execute();
            }
            $row = User::find()->where(['userid' => $uuid])->select(['id'])->asArray()->one();
            return $row['id'];
        } catch (\Exception $e) {
            LogHelp::message('register error:' . $e->getMessage(), 'wechat');
            throw new \Exception('微信用户注册失败');
        }
    }
}